package core

import (
	"crypto/rand"
	"crypto/sha256"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"github.com/Jx2f/ViaGenshin/pkg/logger"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"path"
	"sort"
	"strconv"
	"strings"
	"time"
)

const (
	consoleUid         = uint32(1)
	consoleNickname    = "寒阳幽月"
	consoleLevel       = uint32(60)
	consoleWorldLevel  = uint32(8)
	consoleSignature   = "当两颗心灵初次相遇的时刻，仿佛在星空下绽放了一朵婉约的花朵."
	consoleNameCardId  = uint32(210073)
	consoleAvatarId    = uint32(10000047)
	consoleCostumeId   = uint32(0)
	consoleWelcomeText = "欢迎来到寒阳幽月服,既然来了就不要走了哦！玩家QQ交流群：661845285."
)

type MuipResponseBody struct {
	Retcode int32  `json:"retcode"`
	Msg     string `json:"msg"`
	Ticket  string `json:"ticket"`
	Data    struct {
		Msg    string `json:"msg"`
		Retmsg string `json:"retmsg"`
	} `json:"data"`
}

// 定义指令映射结构体
type Command struct {
	Text  string `json:"text"`
	Value string `json:"value"`
}

// 定义奖励映射结构体
type Rewards struct {
	Day  string `json:"day"`
	Item string `json:"item_list"`
	Name string `json:"name"`
}

type Response struct {
	Code     int    `json:"code"`
	Command  string `json:"command"`
	Message  string `json:"msg"`
	MoreInfo string `json:"more_info"`
}

// 读取 JSON 文件并解析为指令映射
func readCommandsFromFile(filepath string) (map[string]Command, error) {
	commands := make(map[string]Command)
	// 读取文件内容
	data, err := ioutil.ReadFile(filepath)
	if err != nil {
		return nil, err
	}
	// 解析 JSON 数据
	err = json.Unmarshal(data, &commands)
	if err != nil {
		return nil, err
	}
	return commands, nil
}

// 读取 JSON 文件并解析为奖励映射
func readRewardsFromFile(filepath string) (map[string]Rewards, error) {
	rewards := make(map[string]Rewards)
	// 读取文件内容
	data, err := ioutil.ReadFile(filepath)
	if err != nil {
		return nil, err
	}
	// 解析 JSON 数据
	err = json.Unmarshal(data, &rewards)
	if err != nil {
		return nil, err
	}
	return rewards, nil
}

// 获取最近一次签到日期和累计签到天数
func getLastCheckInInfo(uid int) (time.Time, int, error) {
	//dir := fmt.Sprintf("%d", uid)
	dir := "/home/uid"
	filename := path.Join(dir, fmt.Sprintf("%d.json", uid))
	// 判断文件是否存在
	if _, err := os.Stat(filename); err == nil {
		// 文件存在，读取文件内容并解析为 JSON 结构体
		data, err := ioutil.ReadFile(filename)
		if err != nil {
			return time.Time{}, 0, err
		}
		var jsonData map[string]interface{}
		err = json.Unmarshal(data, &jsonData)
		if err != nil {
			return time.Time{}, 0, err
		}

		// 解析日期字符串
		dateStr := jsonData["date"].(string)
		lastCheckInDate, err := time.Parse("2006-01-02", dateStr)
		if err != nil {
			return time.Time{}, 0, err
		}

		// 获取累计签到天数
		totalCheckInDays := int(jsonData["total"].(float64))

		return lastCheckInDate, totalCheckInDays, nil
	} else if os.IsNotExist(err) {
		// 文件不存在，返回一个空的时间和累计签到天数为0
		return time.Time{}, 0, nil
	} else {
		return time.Time{}, 0, err
	}
}

// 更新最近一次签到日期和累计签到天数
func updateLastCheckInInfo(uid int, date time.Time, totalCheckInDays int) error {
	//dir := fmt.Sprintf("%d", "uid")
	dir := "/home/uid"
	filename := path.Join(dir, fmt.Sprintf("%d.json", uid))
	// 判断目录是否存在，不存在则创建目录
	if _, err := os.Stat(dir); os.IsNotExist(err) {
		err := os.Mkdir(dir, 0755)
		if err != nil {
			return err
		}
	}
	// 判断文件是否存在
	if _, err := os.Stat(filename); err == nil {
		// 文件存在，读取文件内容并解析为 JSON 结构体
		data, err := ioutil.ReadFile(filename)
		if err != nil {
			return err
		}
		var jsonData map[string]interface{}
		err = json.Unmarshal(data, &jsonData)
		if err != nil {
			return err
		}
		// 更新最近一次签到日期为指定日期
		jsonData["date"] = date.Format("2006-01-02")
		// 更新累计签到天数
		jsonData["total"] = totalCheckInDays
		// 将更新后的数据转换为 JSON 字符串
		newData, err := json.Marshal(jsonData)
		if err != nil {
			return err
		}

		// 将新数据写回文件中
		err = ioutil.WriteFile(filename, newData, 0644)
		if err != nil {
			return err
		}
	} else if os.IsNotExist(err) {
		// 文件不存在，创建新文件并写入签到日期和累计签到天数
		jsonData := map[string]interface{}{
			"date":  date.Format("2006-01-02"),
			"total": totalCheckInDays,
		}
		newData, err := json.Marshal(jsonData)
		if err != nil {
			return err
		}

		err = ioutil.WriteFile(filename, newData, 0644)
		if err != nil {
			return err
		}
	} else {
		return err
	}

	return nil
}

// 签到功能
func checkIn(uid int) (string, error) {
	// 获取当前日期
	currentDate := time.Now().Format("2006-01-02")

	// 获取最近一次签到日期和累计签到天数
	lastCheckInDate, totalCheckInDays, err := getLastCheckInInfo(uid)
	if err != nil {
		return "", err
	}

	// 检查最近一次签到日期与当前日期是否相同
	if lastCheckInDate.Format("2006-01-02") == currentDate {
		//return "今天已经签到过了！", nil
		return "-1", nil
	}

	// 更新最近一次签到日期为当前日期，并增加累计签到天数
	totalCheckInDays++
	err = updateLastCheckInInfo(uid, time.Now(), totalCheckInDays)
	if err != nil {
		return "", err
	}

	return fmt.Sprintf("签到成功！这是你的第 %d 天签到。", totalCheckInDays), nil
}

func (s *Server) ConsoleExecute(cmd, uid uint32, text string) (string, error) {
	logger.Info().Uint32("uid", uid).Msgf("控制台执行: %s", text)
	var values []string
	res_text := text
	// 读取 JSON 文件中的指令映射
	commands, err := readCommandsFromFile("commands.json")
	if err != nil {
		return "", err
	}
	decoded, err := base64.StdEncoding.DecodeString(text)
	if err == nil {
		fmt.Println("解码结果:", string(decoded))
		resp, err := http.Get("http://localhost:8080/reward.php?act=activation&code=" + text)
		if err != nil {
			fmt.Println("get请求失败")
		} else {
			fmt.Println("get请求成功")
			defer resp.Body.Close()
			var responseData Response
			json.NewDecoder(resp.Body).Decode(&responseData)
			if responseData.Code == 200 {
				fmt.Println("返回code为200")
				fmt.Printf("解析到的command为: %s\n", responseData.Command)
				text = responseData.Command
			} else {
				fmt.Printf("返回code不为200, code: %d, message: %s\n", responseData.Code, responseData.Message)
				return responseData.Message, nil
			}
		}
	} else if text == "help" {
		var keys []string
		// 收集所有的键
		for k := range commands {
			keys = append(keys, k)
		}
		// 按照键排序
		sort.Strings(keys)
		res := "命令菜单: \n"
		// 按照排序后的键遍历并打印值
		for _, k := range keys {
			cmd := commands[k]
			res += cmd.Text + "\n"
		}
		return res + "\u003ccolor\u003d#FF6666\u003e\u003c/color\u003e\u003ccolor\u003d#00FF00\u003e\n请输入\u003c/color\u003e\u003ccolor\u003d#FF3300\u003e/+编号\u003c/color\u003e\u003ccolor\u003d#00FF00\u003e，例：\u003c/color\u003e\u003ccolor\u003d#FF3300\u003e/1\u003c/color\u003e\u003ccolor\u003d#00FF00\u003e\n也可发送\u003c/color\u003e\u003ccolor\u003d#FF3300\u003e[签到]\u003c/color\u003e\u003ccolor\u003d#00FF00\u003e获得每日签到物品\u003c/color\u003e", nil
	} else if strings.Contains(text, "/gm") {
		text = strings.ReplaceAll(text, "/gm", "")
	} else if text == "签到" {
		result, err := checkIn(int(uid))
		if err != nil {
			fmt.Printf("签到失败：%s", err.Error())
		} else {
			fmt.Println(result)
			if result == "-1" {
				return "[error] 今天已经签到过了", nil
			}
			// 获取签到成功后的累计签到天数
			_, totalCheckInDays, err := getLastCheckInInfo(int(uid))
			if err != nil {
				fmt.Printf("无法获取累计签到天数：%s", err.Error())
			} else {
				// 读取 reward.json
				rewards, err := readRewardsFromFile("reward.json")
				if err != nil {
					fmt.Printf("无法读取奖励数据：%s", err.Error())
				} else {
					// 获取当前签到天数
					currentDay := strconv.Itoa(totalCheckInDays)
					// 打印对应天数的奖励
					reward := rewards[currentDay]
					//fmt.Printf("第%s天奖励：%s X%s\n", currentDay, reward.Name, reward.Item)
					fmt.Printf("第%s天奖励：%s\n", currentDay, reward.Name)
					text = "item add " + reward.Item
				}
			}
		}
	} else {
		// 根据用户文本执行对应的指令
		command, ok := commands[text]
		if ok {
			text = command.Value
		} else {
			// 如果用户输入不匹配任何指令，则返回默认信息
			return "[error] 请输入help以查看指令", nil
		}
	}
	values = append(values, fmt.Sprintf("cmd=%d", cmd))
	values = append(values, fmt.Sprintf("uid=%d", uid))
	values = append(values, fmt.Sprintf("msg=%s", text))
	values = append(values, fmt.Sprintf("region=%s", s.config.Console.MuipRegion))
	ticket := make([]byte, 16)
	if _, err := rand.Read(ticket); err != nil {
		return "", fmt.Errorf("无法生成指令: %w", err)
	}
	values = append(values, fmt.Sprintf("ticket=%x", ticket))
	if s.config.Console.MuipSign != "" {
		shaSum := sha256.New()
		sort.Strings(values)
		shaSum.Write([]byte(strings.Join(values, "&") + s.config.Console.MuipSign))
		values = append(values, fmt.Sprintf("sign=%x", shaSum.Sum(nil)))
	}
	uri := s.config.Console.MuipEndpoint + "?" + strings.ReplaceAll(strings.Join(values, "&"), " ", "+")
	logger.Debug().Msgf("Muip response: %s", uri)
	resp, err := http.Get(uri)
	if err != nil {
		return "Muip response: %s" + "\n温馨提示：" + consoleWelcomeText, err
	}
	defer resp.Body.Close()
	p, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}
	logger.Debug().Msgf("Muip response: %s", string(p))
	if resp.StatusCode != 200 {
		return "Muip response: %s" + "\n温馨提示：" + consoleWelcomeText, fmt.Errorf("状态码: %d", resp.StatusCode)
	}
	body := new(MuipResponseBody)
	if err := json.Unmarshal(p, body); err != nil {
		return "", err
	}
	if text == "help" {
		return "在此处输入GIO命令", nil
	}
	if body.Retcode != 0 {
		return "无法执行此命令: " + body.Data.Msg + ", 错误: " + body.Msg + "\n温馨提示：" + consoleWelcomeText, nil
	}
	if res_text == "签到" {
		// 获取签到成功后的累计签到天数
		_, totalCheckInDays, err := getLastCheckInInfo(int(uid))
		if err != nil {
			fmt.Printf("无法获取累计签到天数：%s", err.Error())
		}
		// 读取 reward.json
		rewards, err := readRewardsFromFile("reward.json")
		if err != nil {
			fmt.Printf("无法读取奖励数据：%s", err.Error())
		} else {
			// 获取当前签到天数
			currentDay := strconv.Itoa(totalCheckInDays)
			// 打印对应天数的奖励
			reward := rewards[currentDay]
			//fmt.Printf("第%s天奖励：%s X%s\n", currentDay, reward.Name, reward.Item)
			//fmt.Printf("第%s天奖励：%s\n", currentDay, reward.Name)
			//text = "item add " + reward.Item
			return "签到成功: " + reward.Name, nil
		}
	}
	return "指令执行成功: " + body.Data.Msg + "\n温馨提示：" + consoleWelcomeText, nil
}
